"""
用户信息表 Schema
"""

import re
from datetime import datetime
from typing import Annotated, Literal, Optional

from annotated_types import Len
from pydantic import Field, field_serializer, field_validator

from app.schemas.base import BaseSchema


class UserBase(BaseSchema):
    """用户信息表 基础模型"""

    username: Optional[str] = Field(default=None, max_length=64, description="用户名", alias="username")
    nickname: Optional[str] = Field(default=None, max_length=64, description="昵称", alias="nickname")
    gender: Optional[int] = Field(default=None, description="性别((1-男 2-女 0-保密)", alias="gender")
    dept_id: Optional[int] = Field(default=None, description="部门ID", alias="deptId")
    avatar: Optional[str] = Field(default=None, max_length=255, description="用户头像", alias="avatar")
    mobile: Optional[str] = Field(default=None, max_length=20, description="联系方式", alias="mobile")
    status: Optional[int] = Field(default=None, description="状态(1-正常 0-禁用)", alias="status")
    email: Optional[str] = Field(default=None, max_length=128, description="用户邮箱", alias="email")
    openid: Optional[str] = Field(default=None, max_length=28, description="微信 openid", alias="openid")


class UserCreate(UserBase):
    """创建用户信息表 模型"""

    password: Optional[str] = Field(default=None, max_length=100, description="密码", alias="password")


class UserUpdate(UserBase):
    """更新用户信息表 模型"""

    username: Optional[str] = Field(default=None, max_length=64, description="用户名", alias="username")
    nickname: Optional[str] = Field(default=None, max_length=64, description="昵称", alias="nickname")
    gender: Optional[int] = Field(default=None, description="性别((1-男 2-女 0-保密)", alias="gender")
    password: Optional[str] = Field(default=None, max_length=100, description="密码", alias="password")
    dept_id: Optional[int] = Field(default=None, description="部门ID", alias="deptId")
    avatar: Optional[str] = Field(default=None, max_length=255, description="用户头像", alias="avatar")
    mobile: Optional[str] = Field(default=None, max_length=20, description="联系方式", alias="mobile")
    status: Optional[int] = Field(default=None, description="状态(1-正常 0-禁用)", alias="status")
    email: Optional[str] = Field(default=None, max_length=128, description="用户邮箱", alias="email")
    openid: Optional[str] = Field(default=None, max_length=28, description="微信 openid", alias="openid")


class UserPublic(UserBase):
    """用户信息表 公共模型，用于API响应"""

    id: int = Field(alias="id", description="主键")
    username: Optional[str] = Field(default=None, alias="username", max_length=64, description="用户名")
    nickname: Optional[str] = Field(default=None, alias="nickname", max_length=64, description="昵称")
    gender: Optional[int] = Field(default=None, alias="gender", description="性别((1-男 2-女 0-保密)")
    dept_id: Optional[int] = Field(default=None, alias="deptId", description="部门ID")
    avatar: Optional[str] = Field(default=None, alias="avatar", max_length=255, description="用户头像")
    mobile: Optional[str] = Field(default=None, alias="mobile", max_length=20, description="联系方式")
    status: Optional[int] = Field(default=None, alias="status", description="状态(1-正常 0-禁用)")
    email: Optional[str] = Field(default=None, alias="email", max_length=128, description="用户邮箱")
    create_time: Optional[datetime] = Field(default=None, alias="createTime", description="创建时间")
    create_by: Optional[int] = Field(default=None, alias="createBy", description="创建人ID")
    update_time: Optional[datetime] = Field(default=None, alias="updateTime", description="更新时间")
    update_by: Optional[int] = Field(default=None, alias="updateBy", description="修改人ID")


class UserPageQuery(BaseSchema):
    """用户信息表 分页查询模型"""

    page_num: int = Field(default=1, min=1, alias="pageNum", description="页码")
    page_size: int = Field(default=10, min=10, max=1000, alias="pageSize", description="每页记录数")
    keywords: Optional[str] = Field(default=None, max_length=128, description="关键字(用户名/昵称/手机号)")
    status: Optional[int] = Field(default=None, description="用户状态(1-正常 0-禁用)")
    dept_id: Optional[int] = Field(default=None, alias="deptId", description="部门ID")
    role_ids: Optional[list[int]] = Field(default=None, alias="roleIds", description="角色ID")
    create_time: Optional[Annotated[list[str], Len(1, 2)]] = Field(
        default=None, alias="createTime", description="创建日期范围 [开始日期, 结束日期]，格式: YYYY-MM-DD"
    )
    field: Optional[Literal["create_time", "update_time"]] = Field(default=None, description="排序的字段")
    direction: Optional[Literal["asc", "desc"]] = Field(default=None, description="排序方式（正序:ASC；反序:DESC）")
    is_root: Optional[bool] = Field(default=None, alias="isRoot", description="是否超级管理员")

    @field_validator("create_time", mode="after")
    @classmethod
    def parse_date_range(cls, v: Optional[list[str]]) -> Optional[list[datetime]]:
        if v is None:
            return None

        # 验证格式并解析为 date
        dates = []
        date_pattern = re.compile(r"^\d{4}-\d{2}-\d{2}$")
        for s in v:
            if not date_pattern.match(s):
                raise ValueError(f"日期格式无效: '{s}'，应为 YYYY-MM-DD")
            try:
                dt = datetime.strptime(s, "%Y-%m-%d")
                dates.append(dt)

            except ValueError as e:
                raise ValueError(f"无效日期: {s}") from e

        if len(dates) == 2 and dates[0] > dates[1]:
            raise ValueError("开始日期不能晚于结束日期")

        return dates


class UserPageView(BaseSchema):
    """用户信息表 视图模型，用于API响应"""

    id: int = Field(alias="id", description="主键")
    username: Optional[str] = Field(default=None, alias="username", max_length=64, description="用户名")
    nickname: Optional[str] = Field(default=None, alias="nickname", max_length=64, description="昵称")
    mobile: Optional[str] = Field(default=None, alias="mobile", max_length=20, description="联系方式")
    gender: Optional[int] = Field(default=None, alias="gender", description="性别((1-男 2-女 0-保密)")
    avatar: Optional[str] = Field(default=None, alias="avatar", max_length=255, description="用户头像")
    status: Optional[int] = Field(default=None, alias="status", description="状态(1-正常 0-禁用)")
    email: Optional[str] = Field(default=None, alias="email", max_length=128, description="用户邮箱")
    dept_name: Optional[str] = Field(default=None, alias="deptName", description="部门名称")
    role_names: Optional[str] = Field(default=None, alias="roleNames", description="角色名称")
    create_time: Optional[datetime] = Field(default=None, alias="createTime", description="创建时间")

    @field_serializer("create_time", when_used="json")
    def serialize_dt(self, dt: Optional[datetime], _info):
        if dt:
            return dt.strftime("%Y-%m-%d %H:%M:%S")
        return None


class UserForm(BaseSchema):
    """用户表单对象"""

    id: Optional[int] = Field(default=None, alias="id", description="用户ID")
    username: Optional[str] = Field(default=None, alias="username", max_length=64, description="用户名")
    nickname: Optional[str] = Field(default=None, alias="nickname", max_length=64, description="昵称")
    mobile: Optional[str] = Field(default=None, alias="mobile", max_length=20, description="联系方式")
    password: Optional[str] = Field(default=None, max_length=100, description="密码", alias="password")
    gender: Optional[int] = Field(default=None, alias="gender", description="性别((1-男 2-女 0-保密)")
    avatar: Optional[str] = Field(default=None, alias="avatar", max_length=255, description="用户头像")
    status: Optional[int] = Field(default=None, alias="status", description="状态(1-正常 0-禁用)")
    email: Optional[str] = Field(default=None, alias="email", max_length=128, description="用户邮箱")
    dept_id: Optional[int] = Field(default=None, alias="deptId", description="部门ID")
    role_ids: Optional[list[int]] = Field(default=None, alias="roleIds", description="角色ID")
    open_id: Optional[str] = Field(default=None, alias="openId", description="微信openId")
    op_id: Optional[int] = Field(default=None, alias="opId", description="操作人ID")

    @field_validator("mobile", mode="after")
    @classmethod
    def validate_mobile(cls, v: Optional[str]) -> Optional[str]:
        if v is None:
            return None
        # 手机号码格式不正确
        if not re.match(r"^1(3\d|4[5-9]|5[0-35-9]|6[2567]|7[0-8]|8\d|9[0-35-9])\d{8}$", v):
            raise ValueError("手机号码格式不正确")

        return v

    @field_validator("status", mode="after")
    @classmethod
    def validate_status(cls, v: Optional[int]) -> Optional[int]:
        if v is None:
            return None
        # 用户状态不正确
        if v not in [0, 1]:
            raise ValueError("用户状态不正确")
        return v

    @field_validator("username", mode="after")
    @classmethod
    def validate_username(cls, v: Optional[str]) -> Optional[str]:
        if v is None:
            return None
        # 用户名不能为空
        if not v:
            raise ValueError("用户名不能为空")
        return v

    @field_validator("nickname", mode="after")
    @classmethod
    def validate_nickname(cls, v: Optional[str]) -> Optional[str]:
        if v is None:
            return None
        # 昵称不能为空
        if not v:
            raise ValueError("昵称不能为空")
        return v

    @field_validator("role_ids", mode="after")
    @classmethod
    def validate_role_ids(cls, v: Optional[list[int]]) -> Optional[list[int]]:
        if v is None:
            return None
        # 用户角色不能为空
        if not v:
            raise ValueError("用户角色不能为空")
        return v


class CurrentUserDTO(BaseSchema):
    """当前登录用户对象"""

    user_id: Optional[int] = Field(default=None, alias="userId", description="用户ID")
    username: Optional[str] = Field(default=None, alias="username", description="用户名")
    nickname: Optional[str] = Field(default=None, alias="nickname", description="用户昵称")
    avatar: Optional[str] = Field(default=None, alias="avatar", description="头像地址")
    roles: Optional[list[str]] = Field(default=None, alias="roles", description="用户角色编码集合")
    perms: Optional[list[str]] = Field(default=None, alias="perms", description="用户权限标识集合")


class ExcelResult(BaseSchema):
    """Excel导出响应结构体"""

    code: str = Field(default="00000", alias="code", description="响应码，来确定是否导入成功")
    valid_count: int = Field(default=0, alias="validCount", description="有效条数")
    invalid_count: int = Field(default=0, alias="invalidCount", description="无效条数")
    message_list: list[str] = Field(default=[], alias="messageList", description="错误提示信息")


class UserProfileVO(BaseSchema):
    """个人中心用户信息"""

    id: Optional[int] = Field(default=None, alias="id", description="用户ID")
    username: Optional[str] = Field(default=None, alias="username", description="用户名")
    nickname: Optional[str] = Field(default=None, alias="nickname", description="用户昵称")
    avatar: Optional[str] = Field(default=None, alias="avatar", description="头像URL")
    gender: Optional[int] = Field(default=None, alias="gender", description="性别")
    mobile: Optional[str] = Field(default=None, alias="mobile", description="手机号")
    email: Optional[str] = Field(default=None, alias="email", description="邮箱")
    dept_name: Optional[str] = Field(default=None, alias="deptName", description="部门名称")
    role_names: Optional[str] = Field(default=None, alias="roleNames", description="角色名称")
    create_time: Optional[datetime] = Field(default=None, alias="createTime", description="创建时间, yyyy-MM-dd")

    @field_validator("create_time", mode="after")
    @classmethod
    def parse_create_time(cls, v: Optional[datetime]) -> Optional[str]:
        if v is None:
            return None
        return v.strftime("%Y-%m-%d")


class UserProfileForm(BaseSchema):
    """个人中心用户信息"""

    id: Optional[int] = Field(default=None, alias="id", description="用户ID")
    username: Optional[str] = Field(default=None, alias="username", description="用户名")
    nickname: Optional[str] = Field(default=None, alias="nickname", description="用户昵称")
    avatar: Optional[str] = Field(default=None, alias="avatar", description="头像URL")
    gender: Optional[int] = Field(default=None, alias="gender", description="性别")
    mobile: Optional[str] = Field(default=None, alias="mobile", description="手机号")
    email: Optional[str] = Field(default=None, alias="email", description="邮箱")
    op_id: Optional[int] = Field(default=None, alias="opId", description="操作人ID")


class PasswordUpdateForm(BaseSchema):
    """修改密码表单"""

    old_password: str = Field(default=None, alias="oldPassword", description="原密码")
    new_password: str = Field(default=None, alias="newPassword", description="新密码")
    confirm_password: str = Field(default=None, alias="confirmPassword", description="确认密码")
    op_id: Optional[int] = Field(default=None, alias="opId", description="操作人ID")
